﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#include "Thread.h"
#include "Tracer.h"
#include "Timer.h"
#include <stdlib.h>

#define THREAD_COUNT_DEFAULT    5  /* 默认线程池线程个数 */

Runnable::Runnable():
m_isStarted(false)
{
}

Runnable::~Runnable()
{
}

bool Runnable::isStarted()
{
    return m_isStarted;
}

Thread::Thread()
{
	m_pRunnableTarget = NULL;
	m_threadStatus = THREAD_STATUS_NEW;
	m_threadID = 0;
	pthread_attr_init(&m_ThreadAttr);
}

Thread::~Thread()
{
	pthread_attr_destroy(&m_ThreadAttr);
}

/**
 *  \brief  启动线程
 *  \param  pRunnable Runnable对象
 *  \return 成功返回true,失败返回false
 *  \note   none
 */
bool Thread::start(Runnable* pRunnable)
{
	if(NULL==pRunnable || m_threadID != 0)
	{
		return false;
	}
	m_pRunnableTarget = pRunnable;
	if(0!=pthread_create(&m_threadID, &m_ThreadAttr, threadEntry, this))
	{
		return false;
	}
	m_threadStatus = THREAD_STATUS_START;
	return true;
}

/* 线程入口点 */
void * Thread::threadEntry(void *arg)
{
	Thread* pThread = (Thread*)arg;
	if(pThread != NULL)
	{
		pThread->threadMain();
	}
	return (void*)0;
}

/* 线程运行函数 */
void Thread::threadMain()
{
	m_threadStatus = THREAD_STATUS_RUNNING;
	m_threadID = pthread_self();
	if(m_pRunnableTarget != NULL)
	{
		m_pRunnableTarget->run();
	}
	m_threadStatus = THREAD_STATUS_EXIT;
	m_threadID = 0;
	pthread_exit(NULL);
}

/**
 *  \brief  判断线程是否正在运行
 *  \param  void
 *  \return 正在运行返回true,否则返回false
 *  \note   none
 */
bool Thread::isRunning()
{
	if(m_threadStatus == THREAD_STATUS_RUNNING)
	{
		return true;
	}
	return false;
}
/**
 *  \brief  获取线程当前状态
 *  \param  void
 *  \return int  线程状态(THREAD_STATUS_E)
 *  \note   none
 */
int Thread::getStatus()
{
    return m_threadStatus;
}
/**
 *  \brief  取消线程
 *  \param  void
 *  \return void
 *  \note   none
 */
bool Thread::cancel()
{
#ifdef OS_ANDROID
	return false;
#else
    if (m_threadID > 0)
    {
    	if (0!=pthread_cancel(m_threadID))
    	{
    		TRACE_ERR_CLASS("pthread cancel error.\n");
    		return false;
    	}
        pthread_join(m_threadID, NULL);
    }
    m_threadID = 0;
	m_threadStatus = THREAD_STATUS_EXIT;
    return true;
#endif
}

/**
 *  \brief  线程休眠
 *  \param  ms 毫秒数
 *  \return void
 *  \note   none
 */
void Thread::msleep(int ms)
{
    Timer::msDelay(ms);
}

/**
 *  \class  TaskInfo_S
 *  \brief  任务参数结构体 
 */
typedef struct{
    Runnable* m_owner;
    SEL_task m_task;
    void* m_arg;
}TaskInfo_S;

/**
 *  \brief  创建任务(子线程)
 *  \param  pRunnable Runnable对象
 *  \param  task 任务方法
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int Thread::createTask(Runnable* owner,SEL_task task,void* taskArg)
{
    pthread_t threadID;
    /* 一定要使用malloc分配arg内存,等线程跑起来后再free;
     * 千万不能直接定义一个临时变量,否则会出现段错误;
     * 原因是:pthread_create返回时线程实际还没运行,
     * 而返回后此函数退出,定义的变量已经失效,因此出错!
     */
    TaskInfo_S *taskInfo = (TaskInfo_S*)malloc(sizeof(TaskInfo_S));
    taskInfo->m_owner=owner;
    taskInfo->m_task=task;
    taskInfo->m_arg=taskArg;
	if(NULL==owner || task == NULL)
	{
	    TRACE_ERR("Thread::createTask,parameter error!\n");
		return STATUS_ERROR;
	}
	if(0!=pthread_create(&threadID, NULL, taskEntry, taskInfo))
	{
	    TRACE_ERR("Thread::createTask,create task thread failed!\n");
		return STATUS_ERROR;
	}
	return STATUS_OK;   
}

/* 任务入口点 */
void * Thread::taskEntry(void *arg)
{
	TaskInfo_S* pTask = (TaskInfo_S*)arg;
	if(pTask->m_owner!=NULL && pTask->m_task!=NULL)
	{
		((pTask->m_owner)->*(pTask->m_task))(pTask->m_arg);
	}
    free(pTask);
    pTask = NULL;
	return (void*)0;
}

/**
 *  \brief  线程池构造函数
 *  \param  none
 *  \return none
 */
ThreadPool::ThreadPool():
m_initFlag(false),
m_maxThreadCount(0),
m_usedThreadCount(0)
{
}
/**
 *  \brief  线程池析构函数
 *  \param  none
 *  \return none
 */
ThreadPool::~ThreadPool()
{
}
/**
 *  \class  ThreadInfo_S
 *  \brief  线程参数结构体 
 */
typedef struct{
    ThreadPool* m_pool;
    int m_index;
}ThreadInfo_S;

/**
 *  \brief  线程池初始化
 *  \param  maxThreadCount 最大线程个数
 *  \return 成功返回true,失败返回false
 */
bool ThreadPool::init(int maxThreadCount)
{
    if (m_initFlag)
    {
        return false;
    }
    if (maxThreadCount<=0)
    {
       maxThreadCount = THREAD_COUNT_DEFAULT;
    }
    m_maxThreadCount=0;
    m_threadVect.clear();
    for(int i=0; i<maxThreadCount; i++)
    {
        pthread_t threadID;
        ThreadInfo_S *threadInfo = (ThreadInfo_S*)malloc(sizeof(ThreadInfo_S));
        threadInfo->m_pool=this;
        threadInfo->m_index=i; 
    	if(0!=pthread_create(&threadID, NULL, threadEntry, threadInfo))
    	{
    	    TRACE_ERR("ThreadPool::createThread,create thread failed!\n");
    		return false;
    	}
        else
        {
            m_threadVect.push_back(NULL);
            m_maxThreadCount++;
        }
    }
    m_initFlag=true;
    return true;
}
/**
 *  \brief  启动线程
 *  \param  runnable 线程运行体
 *  \param  priority 线程运行优先级
 *  \return 成功返回true,失败返回false
 */
bool ThreadPool::start(Runnable* runnable, int priority)
{
    if (runnable==NULL)
    {
        return false;
    }
    AutoLock lock(&m_vectLock);
    if (m_usedThreadCount>=m_maxThreadCount)
    {
        return false;
    }
    for(int i=0; i<m_maxThreadCount; i++)
    {
        if (m_threadVect[i]==NULL)
        {
			runnable->m_isStarted=true;
            m_threadVect[i]=runnable;
	        return true; 
        }
    }
    return false; 
}
/**
 *  \brief  停止线程
 *  \param  runnable 线程运行体
 *  \return 成功返回true,失败返回false
 */
bool ThreadPool::cancel(Runnable* runnable)
{
    if (runnable==NULL)
    {
        return true;
    }
    AutoLock lock(&m_vectLock);
    for(int i=0; i<m_maxThreadCount; i++)
    {
        if (m_threadVect[i]==runnable)
        {
            m_threadVect[i]->m_isStarted=false;
            m_threadVect[i]=NULL;
            return true;
        }
    }
    return false;
}
/**
 *  \brief  返回当前线程池最大线程个数
 *  \param  none
 *  \return 线程个数
 */
int ThreadPool::maxThreadCount()
{
    return m_maxThreadCount;
}
/**
 *  \brief  返回当前可用线程个数
 *  \param  none
 *  \return 线程个数
 */
int ThreadPool::idleThreadCount()
{
    return m_maxThreadCount-m_usedThreadCount;
}

void ThreadPool::startThread(int index)
{
    if (index<m_maxThreadCount)
    {
        m_vectLock.lock();
        Runnable* runnable = m_threadVect[index];
        if (runnable!=NULL)
        {
            m_usedThreadCount++;
            m_vectLock.unLock();
            runnable->run();
            /* 线程使用完毕,正常退出 */
            runnable->m_isStarted=false;
            m_vectLock.lock();
            m_threadVect[index]=NULL;
            m_usedThreadCount--;
            m_vectLock.unLock();
        }
        else
        {
            m_vectLock.unLock();
        }
        
    }
}
/* 线程入口点 */
void * ThreadPool::threadEntry(void *arg)
{
    ThreadInfo_S* threadInfo = (ThreadInfo_S*)arg;
    ThreadPool* threadPool = threadInfo->m_pool;
    int threadIndex = threadInfo->m_index;
	if(threadPool!=NULL && threadIndex>=0)
	{
	    while(1)
	    {
	        threadPool->startThread(threadIndex);
            Thread::msleep(100);
        }
	}
    free(threadInfo);
    threadInfo = NULL;
	return (void*)0;
}

